package com.leixin.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Map;

/**
 * @Description: TODO
 * @Date : 2020/7/7
 * @Company : TODO
 * @Author : LeiXin
 */
public class UrlConnection {

    private static final Logger log = LoggerFactory.getLogger(UrlConnection.class);

    private static final String CONTENT_TYPE = "Content-Type";
    private static final String TYPE_GET = "GET";
    private static final String TYPE_POST = "POST";

    private static final String CONTENT_TYPE_JSON = "application/json;charset=utf-8";
    private static final String CONTENT_TYPE_FORM = "application/x-www-form-urlencoded";
    private static final String CONTENT_TYPE_FILE = "application/octet-stream";
    private static final String CONTENT_TYPE_MULTIPART = "multipart/form-data";
    private static final String CONTENT_TYPE_TEXT_HTML = "text/html;charset=utf-8";
    private static final String CONTENT_TYPE_TEXT_XML = "text/xml;charset=utf-8";
    private static final String CONTENT_TYPE_TEXT_PLAIN = "text/plain;charset=utf-8";
    private static final String CONTENT_TYPE_MARKDOWN = "text/x-markdown;charset=utf-8";

    public static void main(String[] args) {
        String json = getJson("http://srv-summary-query.bmg.rockontrol.com/data?keyType=CITY&keys=211300000&timeType=YEARADD&startTime=2019-12-31&endTime=2021-12-31&sort=ASC");
        System.out.println(json);
    }

    public static String getJson(String url) {
        try {
            HttpURLConnection connection = getConnection(url);
            connection.setRequestProperty(CONTENT_TYPE, CONTENT_TYPE_JSON);
            return send(connection, null);
        } catch (Exception e) {
            log.error(e.getMessage());
            return null;
        }
    }

    public static String postJson(String url, String data, Map<String, String> headers) {
        try {
            HttpURLConnection connection = postConnection(url);
            connection.setRequestProperty(CONTENT_TYPE, CONTENT_TYPE_JSON);

            // 添加请求头
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                connection.setRequestProperty(entry.getKey(), entry.getValue());
            }

            return send(connection, data);
        } catch (Exception e) {
            log.error(e.getMessage());
            return null;
        }
    }

    public static String postJson(String url, String data) {
        try {
            HttpURLConnection connection = postConnection(url);
            connection.setRequestProperty(CONTENT_TYPE, CONTENT_TYPE_JSON);
            return send(connection, data);
        } catch (Exception e) {
            log.error(e.getMessage());
            return null;
        }
    }

    public static String postMarkdown(String url, String data) {
        try {
            HttpURLConnection connection = postConnection(url);
            connection.setRequestProperty(CONTENT_TYPE, CONTENT_TYPE_MARKDOWN);
            return send(connection, data);
        } catch (Exception e) {
            log.error(e.getMessage());
            return null;
        }
    }

    public static String postFile(String urlStr, String data, String fileName, InputStream is) {

        final String BOUNDARY = "-------------------------WERCIOEWNG";

        HttpURLConnection conn = null;
        OutputStream out = null;
        try {
            conn = postConnection(urlStr);
            conn.setReadTimeout(30000);
            conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)");
            conn.setRequestProperty(CONTENT_TYPE, CONTENT_TYPE_MULTIPART + "; boundary=" + BOUNDARY);

            out = conn.getOutputStream();

            byte[] endData = ("\r\n--" + BOUNDARY + "--\r\n").getBytes();
            String strBuf = "\r\n" + "--" + BOUNDARY + "\r\n" +
                    "Content-Disposition: form-data; name=\"files\"; filename=\"" + fileName + "\"\r\n" +
                    "Content-Type:" + CONTENT_TYPE_FILE + "\r\n\r\n";
            out.write(strBuf.getBytes());
            int bytes;
            byte[] bufferOut = new byte[1024];
            while ((bytes = is.read(bufferOut)) != -1) {
                out.write(bufferOut, 0, bytes);
            }

            out.write(endData);
            out.flush();

            return send(conn, data);
        } catch (Exception e) {
            log.error(e.getMessage());
            return null;
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException ignored) {
                }
            }
            if (out != null) {
                try {
                    out.close();
                } catch (IOException ignored) {
                }
            }
        }
    }

    public static byte[] getImageFile(String url) {
        try {
            ByteArrayOutputStream baos = null;
            InputStream is = null;
            HttpURLConnection conn = getConnection(url);
//            connection.setRequestProperty(CONTENT_TYPE, CONTENT_TYPE_JSON);
            try {
                conn.connect();

                int statusCode = conn.getResponseCode();
                if (statusCode != 200) {
                    log.error("Http Request StatusCode({}) Invalid.", statusCode);
                    throw new RuntimeException(inputStreamToStr(conn.getErrorStream()));
                }

                baos = new ByteArrayOutputStream();

                try {
                    is = conn.getInputStream();
                    final byte[] by = new byte[1024];
                    int len = -1;
                    while ((len = is.read(by)) != -1) {
                        baos.write(by, 0, len);
                    }
                } finally {
                    if (is != null) {
                        is.close();
                    }
                }
                return baos.toByteArray();
            } finally {
                if (baos != null) {
                    baos.close();
                }
                if (conn != null) {
                    conn.disconnect();
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            return null;
        }
    }

    private static HttpURLConnection getConnection(String url) throws IOException {
        HttpURLConnection connection = openConnection(url);
        connection.setRequestMethod(TYPE_GET);
        return connection;
    }

    private static HttpURLConnection postConnection(String url) throws IOException {
        HttpURLConnection connection = openConnection(url);
        connection.setRequestMethod(TYPE_POST);
        return connection;
    }

    private static HttpURLConnection openConnection(String url) throws IOException {
        // connection
        HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();

        // connection setting
        connection.setDoOutput(true);
        connection.setDoInput(true);
        connection.setUseCaches(false);
        connection.setReadTimeout(5 * 1000);
        connection.setConnectTimeout(3 * 1000);
        connection.setRequestProperty("connection", "Keep-Alive");
        connection.setRequestProperty("Accept-Charset", StandardCharsets.UTF_8.name());
        return connection;
    }

    private static String send(HttpURLConnection conn, String data) throws IOException {

        try {
            conn.connect();

            if (data != null && data.trim().length() > 0) {
                DataOutputStream dos = null;
                try {
                    dos = new DataOutputStream(conn.getOutputStream());
                    dos.write(data.getBytes(StandardCharsets.UTF_8));
                    dos.flush();
                } finally {
                    if (conn != null) {
                        dos.close();
                    }
                }
            }

            int statusCode = conn.getResponseCode();
            if (statusCode != 200) {
                log.error("Http Request StatusCode({}) Invalid.", statusCode);
                throw new RuntimeException(inputStreamToStr(conn.getErrorStream()));
            }
            return inputStreamToStr(conn.getInputStream());
        } finally {
            if (conn != null) {
                conn.disconnect();
            }
        }
    }

    private static String inputStreamToStr(InputStream is) throws IOException {

        BufferedReader br = null;

        StringBuilder result = new StringBuilder();

        try {
            br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
            String line;
            while ((line = br.readLine()) != null) {
                result.append(line);
            }
        } finally {
            if (br != null) {
                br.close();
            }
        }
        return result.toString();
    }

    private static String inputStreamToByteArr(InputStream is) throws IOException {

        BufferedReader br = null;

        StringBuilder result = new StringBuilder();

        try {
            br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
            String line;
            while ((line = br.readLine()) != null) {
                result.append(line);
            }
        } finally {
            if (br != null) {
                br.close();
            }
        }
        return result.toString();
    }

}
